﻿using System;
using System.Collections.Generic;
using System.Text;
using JFLogic.Wrapper;
using System.Net;
using JFLogic.Utils;
using System.Web;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Threading;
using System.Collections;
using System.IO;
using Model;
using JFLogic.Logic.Donee;
using JFLogic.Logic.Exchange;
using JFLogic.Logic.CodeRepo;
using JFLogic.Logic.JFSession;
using JFLogic.Logic.Fail;

namespace JFLogic.Logic.JF
{
    public class JFBLL
    {
        private string referer = "";

        private string imgPath = System.Configuration.ConfigurationManager.AppSettings["BasePath"] + "img\\";

        public string sid { get; set; }

        /// <summary>
        /// 积分
        /// </summary>
        private int userCurrentIntegral = 0;

        /// <summary>
        /// 记忆的缓存Key
        /// </summary>
        private string memcacheKey = "";

        private HttpUtils httpUtils = null;

        private const string LOGINGETURL = "https://jf.10086.cn/login/login.jsp";

        private const string ISUSERLOGIN = "http://jf.10086.cn/asynlogin/user/web/UserLoginAction?action=isUserLogin&time=";

        private const string ISLOGINBEFOR = "http://jf.10086.cn/asynlogin/ngves.asiainfo.portal.user.web.UserLoginAction?action=isLoginBefore";

        private const string IMAGERAND = "http://jf.10086.cn/imageRand";

        private const string LOGIN = "http://jf.10086.cn/asynlogin/ngves.asiainfo.portal.user.web.UserLoginAction?action=login";

        private const string PRODUCTURL = "http://jf.10086.cn/ware/100000004824204.html";

        private const string PRODUCTID = "100000004824204";

        private const string PRO_GETLESSSTORAGE = "http://jf.10086.cn/portal/ware/web/WareDetailAction?action=getLessStorage";

        private const string PRO_GETWAREDESCVALUE = "http://jf.10086.cn/portal/ware/web/WareDetailAction?action=getWareDescValue";

        private const string CHECKUSER = "http://jf.10086.cn/portal/order/web/UserOrderAction?action=checkUserInfo";

        private const string SAVEASSIGNEEINFOS = "http://jf.10086.cn/portal/user/web/UserAccountAction?action=saveAssigneeInfos";

        private const string GETASSIGNEEINFO = "http://jf.10086.cn/portal/user/web/UserAccountAction?action=getAssigneeInfo";

        private const string SENDTRANSFERCONFIRMCODE = "http://jf.10086.cn/portal/ngves.asiainfo.portal.order.web.UserOrderAction?action=sendTranferConfirmCode";

        private const string TRANSFERPOINTS = "http://jf.10086.cn/portal/user/web/UserAccountAction?action=transferPoints";

        private string phone;
        private string pwd;

        public JFBLL(string _phone, string _pwd, string _sid, string _jsessionid)
        {

            if (!Directory.Exists(imgPath))
            {
                Directory.CreateDirectory(imgPath);
            }
            imgPath = imgPath + DateTime.Now.ToString("yyyyMMdd") + "\\";
            if (!Directory.Exists(imgPath))
            {
                Directory.CreateDirectory(imgPath);
            }
            phone = _phone;
            pwd = _pwd;
            sid = _sid;
            httpUtils = new HttpUtils(_sid);

            if (!string.IsNullOrEmpty(_jsessionid))
            {
                CookieContainer CC = new CookieContainer();
                Cookie cookie = new Cookie();
                cookie.Path = "";
                cookie.Name = "JFUSERID1";
                cookie.Value = _jsessionid;
                cookie.Domain = "jf.10086.cn";
                cookie.Expires = DateTime.Now.AddDays(180);
                CC.Add(cookie);

                httpUtils.WriteCookiesToDisk(CC);    
            }
            
        }

        public JFBLL(string _sid)
            : this("", "", _sid)
        {

        }

        public JFBLL(string _phone, string _pwd, string _sid)
            : this(_phone, _pwd, _sid, null)
        {

        }

        private string Get_LoginUrl()
        {
            return httpUtils.DoGet(LOGINGETURL, null);
        }

        private string Post_IsUserLogin(bool first)
        {
            //检测是否登陆成功， 可以监测积分
            if (first)
            {
                referer = "http://jf.10086.cn/login/login.jsp";
            }
            else
            {
                referer = PRODUCTURL;
            }



            string content = "time=" + HttpUtils.RunJavascript("new Date().getTime().toString(36);");
            string result = httpUtils.DoPost(ISUSERLOGIN, content, referer);


            return result;
        }

        private string Post_ISLOGINBEFOR()
        {
            string content = "mobilePhone=" + phone;
            return httpUtils.DoPost(ISLOGINBEFOR, content, referer);
        }

        private bool Down_IMAGERAND()
        {
            string url = IMAGERAND + "?t=" + HttpUtils.RunJavascript("new Date().getTime().toString(36);");
            return httpUtils.Download(url, imgPath, sid + ".jpg", "");
        }

        /// <summary>
        /// 识别验证码
        /// </summary>
        /// <returns></returns>
        public CodeInfo RecognizeRadon()
        {
            string fullPath = imgPath + sid + ".jpg";
            return WrapperUtil.getInstance().recognize(fullPath);
        }

        /// <summary>
        /// 下载验证码
        /// </summary>
        /// <returns></returns>
        public bool GetRadon()
        {
            Get_LoginUrl();

            Thread.Sleep(1000);

            Post_IsUserLogin(true);

            return Down_IMAGERAND();
        }



        public string Post_LOGIN(string radom)
        {
            WebHeaderCollection headers = new WebHeaderCollection();
            headers.Add("x-requested-with", "XMLHttpRequest");
            string content = "mobilePhone=" + phone;
            content += "&code=" + radom;
            content += "&password=" + EncodePwd.encodeForPwd(pwd);
            content += "&isRememberMe=1";

            //需检测登陆是否成功
            //成功{"forwareURL":"/","msg":"SYS_MSG_AUTHENTICATE_SUCCESS"}
            //密码错误 {"msg":"A107"}
            //验证码错误 {"msg":"11006"}

            return httpUtils.DoPost(LOGIN, content, referer, headers);
        }

        public string Get_PRODUCTURL()
        {
            return httpUtils.DoGet(PRODUCTURL, null);
        }

        public string Post_PRO_GETLESSSTORAGE()
        {
            string content = "ware_id=" + PRODUCTID;
            return httpUtils.DoPost(PRO_GETLESSSTORAGE, content, referer);
        }

        public string Post_PRO_GETWAREDESCVALUE()
        {
            string content = "wareIds=" + PRODUCTID;
            return httpUtils.DoPost(PRO_GETWAREDESCVALUE, content, referer);
        }

        public string Post_CHECKUSER()
        {
            //可以获得积分情况
            string content = "";
            return httpUtils.DoPost(CHECKUSER, content, referer);
        }

        public string Post_SAVEASSIGNEEINFOS(string phone, string name, string card)
        {
            //{"code":"03","msg":"【GA08】该转让人的有效受让人个数已经达到上限，新增失败"}
            referer = "http://jf.10086.cn/portal/user/web/UserAccountAction?action=addAssigneeInfos";
            string content = "assigneeMobile=" + phone;
            content += "&assigneeName=" + HttpUtility.UrlEncode(name, Encoding.UTF8);
            content += "&certificateType=01";
            content += "&certificateNum=" + card;
            return httpUtils.DoPost(SAVEASSIGNEEINFOS, content, referer);

        }

        /// <summary>
        /// 获取已经添加的受赠人信息
        /// </summary>
        /// <returns></returns>
        public string Get_GETASSIGNEEINFO()
        {
            return httpUtils.DoGet(GETASSIGNEEINFO, referer);
        }

        /// <summary>
        /// 发送短信验证码
        /// </summary>
        /// <returns></returns>
        public string Post_SENDTRANSFERCONFIRMCODE()
        {
            referer = "http://jf.10086.cn/portal/user/web/UserAccountAction?action=toTransferPoints";
            return httpUtils.DoPost(SENDTRANSFERCONFIRMCODE, "", referer);
        }

        /// <summary>
        /// 确认转赠
        /// </summary>
        /// <param name="phone"></param>
        /// <param name="confirmCode"></param>
        /// <param name="integer"></param>
        /// <returns>受让人账户有问题，返回 {"code":"9999","msg":"【受让人账户状态异常】"}</returns>
        public string Post_TRANSFERPOINTS(string phone, string confirmCode, int integer)
        {
            string content = "integer=" + integer.ToString();
            content += "&transferNum=" + phone;
            content += "&confirmCode=" + confirmCode;

            string result = httpUtils.DoPost(TRANSFERPOINTS, content, referer);

            return result;
        }

        /// <summary>
        /// 解析返回的人员信息
        /// </summary>
        /// <param name="isLoginUser"></param>
        /// <returns></returns>
        public Hashtable AnalizeIsLoginUser(string isLoginUser)
        {
            //{"status":"USER_LOGIN_STATUS_LOGIN","localCount":"N","flagIntegralDetail":true,"sum":"3","info":{"provCode":"ha","mobileBrand":"2","mobileLevel":"100","starLevelName":"","totalPoint":"0","mobileNumber":"15136173912","userCurrentIntegral":"979","loginFailNum":0,"memcacheKey":"f9f2fde67db3d6d62272287f7d49de1a"}}
            JObject userJsonObj = JObject.Parse(isLoginUser);

            if (userJsonObj.Property("info") != null)
            {
                JObject userInfo = (JObject)userJsonObj["info"];

                userCurrentIntegral = Convert.ToInt32(userInfo["userCurrentIntegral"].ToString());
                memcacheKey = userInfo["memcacheKey"].ToString();

                Hashtable ht = new Hashtable();
                ht.Add("integra", userCurrentIntegral);
                ht.Add("memcacheKey", memcacheKey);
                return ht;
            }
            return null;
        }

        /// <summary>
        /// 解析请求赠送积分时的请求是否通过
        /// </summary>
        /// <param name="transferPoint"></param>
        /// <returns></returns>
        private Hashtable AnalizeTRANSFERPOINTS(string transferPoint)
        {
            //{"code":"8888","msg":"短信验证码错误"}
            //{"code":"0000","msg":"成功"}
            JObject jo = JObject.Parse(transferPoint);
            if (jo.Property("code") != null)
            {
                Hashtable ht = new Hashtable();
                ht.Add("code", jo["code"]);
                ht.Add("code", jo["msg"]);
                return ht;
            }
            return null;
        }

        /// <summary>
        /// 免验证码登陆
        /// </summary>
        /// <returns></returns>
        public Hashtable UserEasyLogin()
        {
            Post_ISLOGINBEFOR();

            Thread.Sleep(100);

            return RealLogin("", false);

        }

        /// <summary>
        /// 快速登录接口
        /// </summary>
        /// <returns></returns>
        public Hashtable UserFastLogin(string radom)
        {
            Post_ISLOGINBEFOR();

            Thread.Sleep(100);

            return RealLogin(radom, true);

        }

        private Hashtable RealLogin(string radom, bool bSaveSession)
        {
            string result = Post_LOGIN(radom);

            //成功{"forwareURL":"/","msg":"SYS_MSG_AUTHENTICATE_SUCCESS"}
            //密码错误 {"msg":"A107"}
            //验证码错误 {"msg":"11006"}

            if (result.IndexOf("SYS_MSG_AUTHENTICATE_SUCCESS") <= -1)
            {
                if (result.IndexOf("11006") >= 0)
                {//如果验证码错误，则重新走一遍 获取验证码流程

                }
                throw GetLoginException(sid, result, radom);
            }

            if (bSaveSession)
            {
                SaveJSessionId();
            }

            string isLoginUserStr = Post_IsUserLogin(true);

            Hashtable ht = AnalizeIsLoginUser(isLoginUserStr);

            return ht;
        }

        public void SaveJSessionId()
        {
            CookieContainer cc = httpUtils.ReadCookiesFromDisk();

            List<Cookie> cookieList = httpUtils.GetAllCookies(cc);

            for (int i = 0; i < cookieList.Count; i++)
            {
                Cookie c = cookieList[i];
                if (c.Name.ToUpper().Equals("JFUSERID1"))
                {
                    var sessionCache = new TB_JFSession_Cache()
                    {
                        JFSessionId = c.Value,
                        Phone = phone,
                        Pass = pwd
                    };

                    JFSessionLogic jfLogic = new JFSessionLogic();
                    jfLogic.Insert(sessionCache);
                    break;
                }
            }

        }

        /// <summary>
        /// 正常登录方式
        /// </summary>
        /// <returns></returns>
        public Hashtable UseCommonLogin()
        {

            Get_LoginUrl();

            Thread.Sleep(100);

            Post_IsUserLogin(true);

            Thread.Sleep(100);

            Post_ISLOGINBEFOR();

            Thread.Sleep(100);

            Down_IMAGERAND();

            CodeInfo cInfo = RecognizeRadon();

            CodeRepoLogic cpLogic = new CodeRepoLogic();
            var codeRepo = new TB_Code_Repo()
            {
                SessionId = sid,
                STime = DateTime.Now,
                CodeState = CodeState.USERD,
                CodeStr = cInfo.ResultCode,
                CodeId = cInfo.CodeId
            };

            string checkResult = CodeUtils.CheckCode(cInfo.ResultCode);//检测验证码识别是否有误

            if (!string.IsNullOrEmpty(checkResult))
            {
                codeRepo.CodeState = CodeState.FAILED;
                cpLogic.Save(codeRepo);

                FailInfo fInfo = new FailInfo();
                fInfo.Remark = "识别的内容为：" + cInfo.ResultCode;
                fInfo.FailId = FailReason.LOGIN_RECOGNIZE_ERR;
                fInfo.FailReason = FailReason.GetReasonStr(FailReason.LOGIN_RECOGNIZE_ERR);
                throw new Exception(Newtonsoft.Json.JsonConvert.SerializeObject(fInfo));
            }
            else
            {
                codeRepo.CodeState = CodeState.USERD;
                cpLogic.Save(codeRepo);
            }

            return RealLogin(cInfo.ResultCode, true);
        }

        private Exception GetLoginException(string sId, string result, string extention)
        {
            int rel = 0;
            string remark = "";
            if (result.IndexOf("A107") > -1)
            {
                remark = result;
                rel = FailReason.LOGIN_PWD_ERR;
            }
            else if (result.IndexOf("11006") > -1)
            {
                remark = "错误的验证码为：" + extention;
                rel = FailReason.LOGIN_CODE_ERR;
            }
            else
            {
                //TODO 数据库记录未知错误
                remark = result;
                rel = FailReason.LOGIN_UNKNOWN_ERR;
            }
            FailInfo fInfo = new FailInfo();
            fInfo.FailId = rel;
            fInfo.FailReason = FailReason.GetReasonStr(rel);
            fInfo.Remark = remark;
            return new Exception(Newtonsoft.Json.JsonConvert.SerializeObject(fInfo));
        }

        /// <summary>
        /// 发送短信验证码
        /// </summary>
        /// <param name="obj"></param>
        public void SendSmsCode(object obj)
        {
            Get_PRODUCTURL();

            Thread.Sleep(100);

            Post_PRO_GETLESSSTORAGE();

            Thread.Sleep(100);

            Post_PRO_GETWAREDESCVALUE();

            Thread.Sleep(100);

            Post_CHECKUSER();

            Thread.Sleep(500);

        }

        public bool transferPoint(TB_Donee donee, string confirmCode, int integra)
        {

            Post_SAVEASSIGNEEINFOS(donee.Phone, donee.UName, donee.UCard);

            Thread.Sleep(100);

            Get_GETASSIGNEEINFO();

            Thread.Sleep(700);

            string result = Post_TRANSFERPOINTS(donee.Phone, confirmCode, integra);

            if (result.IndexOf("0000") > -1)
            {
                return true;
            }
            else
            {
                throw GetExchageException(result);
            }
        }

        private Exception GetExchageException(string result)
        {
            int rel = 0;

            if (result.IndexOf("8888") > -1)
            {//短信验证码错误
                rel = FailReason.EXCHANGE_SMSCODE_ERR;
            }
            else if (result.IndexOf("9999") > -1)
            {//受让人账户受限
                rel = FailReason.EXCHANGE_PERSON_ERR;
            }
            else
            {
                rel = FailReason.EXCHANGE_UNKNOWN_ERR;
            }
            FailInfo fInfo = new FailInfo();
            fInfo.FailId = rel;
            fInfo.FailReason = FailReason.GetReasonStr(rel);
            fInfo.Remark = result;
            return new Exception(Newtonsoft.Json.JsonConvert.SerializeObject(fInfo));
        }

    }

}
